/*
 *  (C) Copyright 2008 Insula T.I. Ltda.
 * 
 *  This file is part of Vulcano.
 *
 *  Vulcano is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Vulcano is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with Vulcano.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.openinsula.vulcano.orm.dao.hibernate;

import static org.junit.Assert.assertEquals;

import java.util.Date;

import org.junit.Test;
import org.openinsula.vulcano.orm.dao.query.spec.AndSpec;
import org.openinsula.vulcano.orm.dao.query.spec.BetweenSpec;
import org.openinsula.vulcano.orm.dao.query.spec.EqualsSpec;
import org.openinsula.vulcano.orm.dao.query.spec.GreaterOrEqualSpec;
import org.openinsula.vulcano.orm.dao.query.spec.GreaterSpec;
import org.openinsula.vulcano.orm.dao.query.spec.InSpec;
import org.openinsula.vulcano.orm.dao.query.spec.LesserOrEqualSpec;
import org.openinsula.vulcano.orm.dao.query.spec.LesserSpec;
import org.openinsula.vulcano.orm.dao.query.spec.LikeSpec;
import org.openinsula.vulcano.orm.dao.query.spec.NotEqualsSpec;
import org.openinsula.vulcano.orm.dao.query.spec.NotNullSpec;
import org.openinsula.vulcano.orm.dao.query.spec.NullSpec;
import org.openinsula.vulcano.orm.dao.query.spec.OrSpec;
import org.openinsula.vulcano.orm.dao.query.spec.SpecVisitor;

public class HqlSpecVisitorTestCase {
	private SpecVisitor<String> visitor = new HqlSpecVisitor();

	@Test
	public void testVisitAndSpec() {
		EqualsSpec equalsSpec = new EqualsSpec("age", 0);
		NotEqualsSpec notEqualsSpec = new NotEqualsSpec("name", null);
		GreaterSpec greaterSpec = new GreaterSpec("date", new Date());

		assertEquals("(k.age = ? and k.name is not null and k.date > ?)", new AndSpec(equalsSpec, notEqualsSpec,
				greaterSpec).accept(visitor));
	}

	@Test
	public void testVisitOrSpec() {
		EqualsSpec equalsSpec = new EqualsSpec("age", null);
		NotEqualsSpec notEqualsSpec = new NotEqualsSpec("name", "");
		LesserOrEqualSpec lesserOrEqualSpec = new LesserOrEqualSpec("code", 0);

		assertEquals("(k.age is null or k.name <> ? or k.code <= ?)", new OrSpec(equalsSpec, notEqualsSpec,
				lesserOrEqualSpec).accept(visitor));
	}

	@Test
	public void testVisitEqualsSpec() {
		EqualsSpec spec = new EqualsSpec("code", null);
		assertEquals("k.code is null", spec.accept(visitor));

		spec.setValue(0);
		assertEquals("k.code = ?", spec.accept(visitor));
	}

	@Test
	public void testVisitNotEqualsSpec() {
		NotEqualsSpec spec = new NotEqualsSpec("code", null);
		assertEquals("k.code is not null", spec.accept(visitor));

		spec.setValue(0);
		assertEquals("k.code <> ?", spec.accept(visitor));
	}

	@Test
	public void testVisitGreaterOrEqualSpec() {
		GreaterOrEqualSpec spec = new GreaterOrEqualSpec("code", 0);
		assertEquals("k.code >= ?", spec.accept(visitor));
	}

	@Test
	public void testVisitGreaterSpec() {
		GreaterSpec spec = new GreaterSpec("code", 0);
		assertEquals("k.code > ?", spec.accept(visitor));
	}

	@Test
	public void testVisitLesserOrEqualSpec() {
		LesserOrEqualSpec spec = new LesserOrEqualSpec("code", 0);
		assertEquals("k.code <= ?", spec.accept(visitor));
	}

	@Test
	public void testVisitLesserSpec() {
		LesserSpec spec = new LesserSpec("code", 0);
		assertEquals("k.code < ?", spec.accept(visitor));
	}

	@Test
	public void testVisitLikeSpec() {
		LikeSpec spec = new LikeSpec("name", "%John%");
		assertEquals("cast(k.name, string) like ?", spec.accept(visitor));
		assertEquals("%John%", spec.getValue());

		spec = new LikeSpec("name", "%John%", false);
		assertEquals("lower(cast(k.name, string)) like ?", spec.accept(visitor));
		assertEquals("%john%", spec.getValue());
	}

	@Test
	public void testVisitNotNullSpec() {
		assertEquals("k.code is not null", new NotNullSpec("code").accept(visitor));
	}

	@Test
	public void testVisitNullSpec() {
		assertEquals("k.code is null", new NullSpec("code").accept(visitor));
	}

	@Test
	public void testVisitBetweenSpec() {
		BetweenSpec spec = new BetweenSpec("code", 0, 0);
		assertEquals("k.code between ? and ?", spec.accept(visitor));
	}

	@Test
	public void testVisitInSpec() {
		InSpec spec = new InSpec("code", 1, 2, 3, 4, 5);
		assertEquals("k.code in (?,?,?,?,?)", spec.accept(visitor));
	}

}
